package com.easylinkin.linkappapi.security.config;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.service.LinkappUserService;
import java.util.List;


public class LinkappPhoneLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
	public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
	public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";

	private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
	private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
	
	private String phoneParameter = "phone";
	
	private String verificationCodeParameter = "verificationCode";
	
	@Resource
	LinkappUserService linkappUserService;
	@Autowired
	private RedisUtil redisUtil;
	private boolean postOnly = true;
	public LinkappPhoneLoginAuthenticationFilter() {
        super(new AntPathRequestMatcher("/phoneLogin", "POST"));
    }

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException {
		if (postOnly && !"POST".equals(request.getMethod())) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}
		
		String phone = obtainPhone(request);
		
		String verificationCode = obtainVerificationCode(request);
		String username = null;
		String password = null;
		LinkappUser query = new LinkappUser();
		if(phone != null) {
			Object obj  = redisUtil.get(phone);
			if (obj != null) {
				if(obj.toString().equalsIgnoreCase(verificationCode)) {
					query.setPhone(phone);
					//20220713 手机号对应账号已不唯一了，增加排除已冻结账号
					query.setLocked(false);
					List<LinkappUser> users = linkappUserService.selectUsers(query);
					if (users.size() > 0) {
						redisUtil.set(phone + "_login", users.get(0), 300);
						username = users.get(0).getUsername();
						password = users.get(0).getPassword();
					}
				}else {
					throw new CustomAuthException("验证码不正确");
				}
			}else {
				throw new CustomAuthException("验证码不正确或已失效，请重新获取");
			}
		}

		if (username == null) {
			username = "error";
			LinkappUser user = new LinkappUser();
			user.setId(-1L);
			user.setUsername(username);
			redisUtil.set(phone + "_login",user,300);
		}

		if (password == null) {
			password = "";
		}
		username = username.trim();
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
		// Allow subclasses to set the "details" property
		setDetails(request, authRequest);
		return super.getAuthenticationManager().authenticate(authRequest);
	}

	class CustomAuthException extends AuthenticationException{

		public CustomAuthException(String msg, Throwable t) {
			super(msg, t);
		}

		public CustomAuthException(String msg) {
			super(msg);
		}
	}

	@Override
	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
		super.setAuthenticationManager(authenticationManager);
	}

	protected String obtainPassword(HttpServletRequest request) {
		return request.getParameter(passwordParameter).replaceAll(" ", "+");
	}

	protected String obtainUsername(HttpServletRequest request) {
		return request.getParameter(usernameParameter);
	}
	
	protected String obtainPhone(HttpServletRequest request) {
		return request.getParameter(phoneParameter);
	}
	
	protected String obtainVerificationCode(HttpServletRequest request) {
		return request.getParameter(verificationCodeParameter);
	}

	protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}

	public void setUsernameParameter(String usernameParameter) {
		this.usernameParameter = usernameParameter;
	}

	public void setPasswordParameter(String passwordParameter) {
		this.passwordParameter = passwordParameter;
	}

	public void setPostOnly(boolean postOnly) {
		this.postOnly = postOnly;
	}

	public final String getUsernameParameter() {
		return usernameParameter;
	}

	public final String getPasswordParameter() {
		return passwordParameter;
	}
}
